﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using TableParsers;
using System.Collections.Specialized;
using System.Windows.Threading;

using SpeakupBackend;
using SpeakupBackend.Classes;

namespace Frontend
{

    class ClassPanelList: ObservableCollection<ClassPanel> 
    {
        public class ClassChangedEventArgs : EventArgs
        {
            public ClassPanel Panel;
            public Class SpeakupClass; 
        }
        
        public ClassPanelList()
        {
            this.CollectionChanged += ClassPanelList_CollectionChanged;
            UseManualMask = false;
        }

        DispatcherTimer HighlightTimer = new DispatcherTimer();

        private bool m_useManualMask = false;
        public bool UseManualMask 
        {
            get 
            { 
                return m_useManualMask; 
            }
            set
            {
                m_useManualMask = value;
                UpdatePanels();
            }
        }

        private ClassPanelMask m_manualMask = null;
        public ClassPanelMask ManualMask
        {
            get
            {
                return m_manualMask;
            }
            set
            {
                m_manualMask = value;
                UpdatePanels();
            }
        }

        private bool m_defaultEnabledStatus = false;
        public bool DefaultEnabledStatus
        {
            get
            {
                return m_defaultEnabledStatus;
            }
            set
            {
                m_defaultEnabledStatus = true;
                UpdatePanels();
            }
        }

        void UpdatePanels()
        {
            if (UseManualMask)
            {
                if (ManualMask == null)
                {
                    EnableItems(new ClassPanelMask(), DefaultEnabledStatus);
                }
                else
                {
                    EnableItems(ManualMask, DefaultEnabledStatus);
                }
            }
            else
            {
                EnableItems(new ClassPanelMask(), true);
            }
        }

        void ClassPanelList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Add)
            {
                if (e.NewItems != null)
                {
                    foreach (ClassPanel item in e.NewItems)
                    {
                        item.SelectionChanged += ItemSelectionChanged;
                        item.HighlightChanged += ItemHighlightChanged;
                    }
                }
            }
            else if (e.Action == NotifyCollectionChangedAction.Remove)
            {
                foreach (ClassPanel item in e.OldItems)
                {
                    item.SelectionChanged -= ItemSelectionChanged;
                    item.HighlightChanged -= ItemHighlightChanged;
                }                
            }            
        }

        void ItemHighlightChanged(object sender, EventArgs e)
        {
            ClassPanel panel = sender as ClassPanel;
            if (panel == null) return;

            if (HighlightTimer != null)
            {
                HighlightTimer.IsEnabled = false;
                HighlightTimer.Stop();                
                HighlightTimer = null;
            }

            if (panel.IsHighlighted)
            {
                HighligtedItem = panel;
            }
            else
            {
                HighligtedItem = null;                
            }

            //automatic highlight
            if (!UseManualMask)
            {
                ClassPanelMask mask = new ClassPanelMask();
                if (HighligtedItem != null)
                {
                    mask[panel.SpeakupClass.Name.Type] = true;

                    HighlightTimer = new DispatcherTimer();
                    HighlightTimer.Interval = TimeSpan.FromMilliseconds(300);
                    HighlightTimer.Tick += (a, b) =>
                    {
                        EnableItems(mask, false);

                        HighlightTimer.Stop();
                        HighlightTimer = null;
                    };

                    HighlightTimer.Start();
                }
                else
                {
                    EnableItems(mask, true);
                }
            }           
        }

        void ItemSelectionChanged(object sender, EventArgs e)
        {
            ClassPanel item = sender as ClassPanel;
            if (item == null) return;

            if (item.IsSelected)
            {
                //deselect previously selected item
                if (SelectedItem != null && SelectedItem != item)
                {
                    SelectedItem.IsSelected = false;
                }
                SelectedItem = item;
            }
            else
            {
                //if currently selected item was selected                
                if (item == SelectedItem)
                {
                    SelectedItem = null;
                }
            }            
        }
        
        public event EventHandler<ClassChangedEventArgs> SelectionChanged;
        protected void OnSelectionChanged(ClassPanel item)
        {
            if (SelectionChanged != null)
            {
                ClassChangedEventArgs args = new ClassChangedEventArgs();                
                args.Panel = item;
                args.SpeakupClass = item != null ? item.SpeakupClass : null;                
                SelectionChanged(this, args);
            }
        }
        
        ClassPanel m_selectedItem = null;
        public ClassPanel SelectedItem 
        { 
            get
            {
                return m_selectedItem;
            }
            private set
            {
                if (value != m_selectedItem)
                {
                    m_selectedItem = value;
                    OnSelectionChanged(m_selectedItem);
                }
            }
        }

        public event EventHandler<ClassChangedEventArgs> HighlightChanged;
        protected void OnHighlightChanged(ClassPanel item)
        {
            if (HighlightChanged != null)
            {
                ClassChangedEventArgs args = new ClassChangedEventArgs();
                args.Panel = item;
                args.SpeakupClass = item != null ? item.SpeakupClass : null;
                HighlightChanged(this, args);
            }
        }

        ClassPanel m_highlightedItem = null;
        public ClassPanel HighligtedItem
        {
            get
            {
                return m_highlightedItem;
            }
            private set
            {
                if (value != m_highlightedItem)
                {
                    m_highlightedItem = value;
                    OnHighlightChanged(m_highlightedItem);
                }
            }
        }
                    
        /// <summary>
        /// Enables items by their type. If type was specified in dictionary
        /// then it will be activate/deactivated (true/false). If some type was not
        /// used in dictionary all items of that type are left unchanged.
        /// </summary>        
        public void EnableItems(ClassPanelMask mask)
        {
            EnableItems(mask, null);
        }

        public void EnableItems(ClassPanelMask mask, bool? enableByDefault)
        {
            foreach (ClassPanel panel in this)
            {
                ClassType type = panel.SpeakupClass.Name.Type;
                if (mask.Keys.Contains(type))
                {
                    panel.IsEnabled = mask[type];                    
                }
                else
                {
                    if (enableByDefault != null)
                    {
                        panel.IsEnabled = enableByDefault ?? false;                        
                    }
                }
            }
        }
    }
}
